package com.functest.util

import groovy.sql.Sql

import java.sql.SQLException
import java.util.concurrent.TimeUnit

import static java.lang.System.currentTimeMillis

/**
 * Created with IntelliJ IDEA.
 * User: DavydovMD
 * Date: 27.02.13
 * Time: 18:07
 * To change this template use File | Settings | File Templates.
 */
@Singleton
class OrmUtil {

    /**
     * Крайне тупая (но кое-как работающая) имплементация SQL like. Используется в ORM (ConditionOp)
     * @param str , Например, 'JavaScript' или 'QBasic'
     * @param inExpr Например, 'JAVA%'  или '_BASIC'
     * @return
     */
    static boolean like(String str, String inExpr) {
        String likeExpr = inExpr.toLowerCase()
                .replace('.', '\\.') // '\\' is escaped to '\'
                .replace('_', '.')
                .replace('%', '.*')
        str.toLowerCase().matches(likeExpr)
    }



    static String lastToken(String string, String splitter = '.') {
        if (string.indexOf(splitter) == -1)
            return string

        org.apache.commons.lang3.StringUtils.split(string, '.').last();

    }


    static String cutLastToken(String string, String splitter = '.') {
        if (string.indexOf(splitter) == -1)
            return string

        String[] arr = org.apache.commons.lang3.StringUtils.split(string, '.')
        StringBuilder b = new StringBuilder();
        for (int i = 0; i < arr.length - 1; i++) {
            b.append(arr[i])
            b.append(splitter)
        }
        b.toString()
    }

    static Object firstCell(Sql db, GString query) {
        try {
            def rowMap = db.firstRow(query)
            if (!rowMap) {
                throw new NoSuchElementException("Nothing was found for query:${query}")
            }
            return rowMap.values().iterator()?.next()
        } catch (SQLException e) {
            throw new RuntimeException("SQL exception when  executing $query agianst $db", e)
        }
    }

    static Object firstCell(Sql db, String query) {
        try {
            def rowMap = db.firstRow(query)
            if (!rowMap) {
                throw new NoSuchElementException("Nothing was found for query:${query}")
            }
            return rowMap.values().iterator()?.next()
        } catch (SQLException e) {
            throw new RuntimeException("SQL exception when  executing $query agianst $db", e)
        }
    }

    private final static Random rnd = new Random(currentTimeMillis())

    static Closure<Object> randomElement = {
        Collection c = delegate as Collection
        if (c.size() == 0) return null

        int n = rnd.nextInt(c.size())
        if (c instanceof List) {
            return (c as List).get(n)
        } else {
            Iterator iter = c.iterator()
            Object res = null
            for (int i = 0; i < n; i++) {
                res = iter.next()
            }
            return res
        }

    } as Closure<Object>


    static GString asGString(Object s) {
        GString.EMPTY.plus(s) as GString
    }

    static int toMillis(int interval, TimeUnit unit) {
        switch (unit) {
            case TimeUnit.NANOSECONDS:
                return interval / 1000000
            case TimeUnit.MICROSECONDS:
                return interval / 1000
            case TimeUnit.MILLISECONDS:
                return interval
            case TimeUnit.SECONDS:
                return interval * 1000
            case TimeUnit.MINUTES:
                return interval * 60000
            case TimeUnit.HOURS:
                return interval * 3600 * 1000
            case TimeUnit.DAYS:
                return interval * 24 * 3600 * 1000
        }
        throw new UnsupportedOperationException("?!!")
    }



    static {
        Collection.metaClass.random {
            Closure<Object> randClosure = OrmUtil.randomElement
            randClosure.delegate = delegate
            randClosure.call()
        }

        Map.metaClass.swapKeysWithValues {
            def ret = [:]

            delegate.each { Map.Entry entry ->
                ret.put(entry.getValue(), entry.getKey())
            }
            ret
        }


        Map.metaClass.applyMapping { Map mapping ->
            def ret = [:]
            delegate.each { Map.Entry entry ->
                ret.put(mapping[entry.getKey()] ?: entry.getKey(), entry.getValue())
            }
            ret
        }

        /**
         *
         */
        Map.metaClass.enrich { Closure<Map> closure ->
            Map ret = new HashMap((Map) delegate)
            Map a = closure.call(delegate)
            ret.putAll(a)
            ret
        }

        Sql.metaClass.firstCell {
            String query ->
                firstCell((Sql) delegate, query)
        }

    }
}
